// Copyright (c) 2023 Huawei Device Co., Ltd.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::structure::*;
use std::{
    cell::RefCell,
    rc::{Rc, Weak},
};

/// The `ElementMethod` trait, which provides some methods similar to `Interface
/// Element`.
///
/// # Association
/// [Interface Element](https://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-745549614)
pub trait ElementMethod: ParentNodeMethod + NodeMethod {
    /// A `NodeMap` that contains all attributes of this node. If there are no
    /// attribute, an empty `NodeMap` is returned.
    ///
    /// # Example
    /// ```
    /// use ylong_xml::{Document, DocumentMethod, ElementMethod};
    ///
    /// let document = Document::new();
    /// let element = document.create_element("Element").unwrap();
    /// let attributes = element.attributes();
    /// assert_eq!(attributes.len(), 0);
    /// ```
    fn attributes(&self) -> NodeMap<Attribute>;

    /// Check if there are some `Attribute`s in this node.
    ///
    /// # Example
    /// ```
    /// use ylong_xml::{Document, DocumentMethod, ElementMethod};
    ///
    /// let document = Document::new();
    /// let element = document.create_element("Element").unwrap();
    /// assert_eq!(element.has_attributes(), false);
    /// ```
    fn has_attributes(&self) -> bool;

    /// Return `true` when an attribute with a given name is specified on
    /// this element, `false` otherwise.
    ///
    /// # Association
    /// [Element::hasAttributeNS](https://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-ElHasAttrNS)
    ///
    /// # Example
    /// ```
    /// use ylong_xml::{Document, DocumentMethod, ElementMethod};
    ///
    /// let document = Document::new();
    /// let element = document.create_element("Element").unwrap();
    /// assert_eq!(element.contain_attribute("Attribute"), false);
    /// ```
    fn contain_attribute(&self, name: &str) -> bool;

    /// Retrieve an attribute value by name.
    ///
    /// # Association
    /// [Element::getAttributeNS](https://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-ElGetAttrNS)
    ///
    /// # Example
    /// ```
    /// use ylong_xml::{Document, DocumentMethod, ElementMethod};
    ///
    /// let document = Document::new();
    /// let element = document.create_element("Element").unwrap();
    /// assert!(element.get_attribute("Attribute").is_none());
    /// ```
    fn get_attribute(&self, name: &str) -> Option<Attribute>;

    /// Add a new attribute. If there is an old value which has the same name
    /// in the map, it will be replaced and returned.
    ///
    /// # Association
    /// [Element::setAttributeNS](https://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-ElSetAttrNS)
    ///
    /// # Example
    /// ```
    /// use ylong_xml::{Document, DocumentMethod, ElementMethod};
    ///
    /// // Create an element.
    /// let document = Document::new();
    /// let mut element = document.create_element("Element").unwrap();
    ///
    /// // Create an attribute.
    /// let attribute = document.create_attribute("Attribute", "Attribute's Value").unwrap();
    ///
    /// // Add the attribute to the element.
    /// assert!(element.set_attribute(attribute).is_none());
    /// ```
    fn set_attribute(&mut self, attr: Attribute) -> Option<Attribute>;

    /// Remove an attribute by name. If no attribute with this name is
    /// found, this method has no effect.
    ///
    /// # Association
    /// [Element::removeAttributeNS](https://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-ElRemAtNS)
    ///
    /// # Example
    /// ```
    /// use ylong_xml::{Document, DocumentMethod, ElementMethod};
    ///
    /// // Create an element.
    /// let document = Document::new();
    /// let mut element = document.create_element("Element").unwrap();
    ///
    /// // Create an attribute.
    /// let attribute = document.create_attribute("Attribute", "Attribute's Value").unwrap();
    ///
    /// // There is no such attribute, so we get `None`.
    /// assert!(element.remove_attribute("Attribute").is_none());
    /// // Add the attribute to the element.
    /// assert!(element.set_attribute(attribute.clone()).is_none());
    /// // Then we will get the attribute when we remove it.
    /// assert_eq!(element.remove_attribute("Attribute"), Some(attribute));
    /// ```
    fn remove_attribute(&mut self, name: &str) -> Option<Attribute>;

    /// Return a list which contains all `Element`s with the given name.
    ///
    /// # Example
    /// ```
    /// use ylong_xml::{Document, DocumentMethod, ElementMethod};
    ///
    /// let document = Document::new();
    /// let element = document.create_element("Element").unwrap();
    /// let list = element.get_elements("ChildElement");
    /// assert!(list.is_empty());
    /// ```
    fn get_elements(&self, name: &str) -> NodeList<Element>;

    /// Return a `NodeList` of all the descendant `Element`s in document order.
    ///
    /// # Example
    /// ```
    /// use ylong_xml::{Document, DocumentMethod, ElementMethod, ParentNodeMethod};
    ///
    /// // Create an element.
    /// let document = Document::new();
    /// let mut element = document.create_element("Element").unwrap();
    ///
    /// // Create two child elements and one child comment.
    /// let child_element1 = document.create_element("ChildElement1").unwrap();
    /// let child_element2 = document.create_element("ChildElement2").unwrap();
    /// let comment = document.create_comment("Comment").unwrap();
    ///
    /// // Add them to the parent element. Now the parent element has three children,
    /// // two of them are `Element`s..
    /// assert!(element.append_child(child_element1.clone()).is_ok());
    /// assert!(element.append_child(child_element2.clone()).is_ok());
    /// assert!(element.append_child(comment).is_ok());
    /// assert_eq!(element.children().len(), 3);
    ///
    /// // ..so we can get a list contains two elements.
    /// let list = element.get_all_elements();
    /// assert_eq!(list.len(), 2);
    /// assert_eq!(list.item(0), Some(child_element1));
    /// assert_eq!(list.item(1), Some(child_element2));
    /// ```
    fn get_all_elements(&self) -> NodeList<Element>;
}

/// The `Element` structure, the instance of `Interface Element`.
///
/// # Association
/// [Interface Element](https://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-745549614)
///
/// # Example
/// ```
/// use ylong_xml::{Document, DocumentMethod, Element};
///
/// // You can generate element in two ways:
/// let document = Document::new();
/// // You can use the `create_element` method of `Document` to create an `Element`.
/// let element1 = document.create_element("Element1");
/// // You can also use the `new` method of `Element` to create an `Element`.
/// let element2 = Element::new("Element2", &document);
/// ```
#[derive(Debug, Clone)]
pub struct Element {
    pub(crate) inner: Rc<RefCell<ElementInner>>,
}

impl Element {
    /// Create an `Element` with the given name and its owner document.
    ///
    /// # Example
    /// ```
    /// use ylong_xml::{Document, Element};
    ///
    /// let document = Document::new();
    /// let element = Element::new("Element", &document);
    /// ```
    pub fn new(name: &str, owner_document: &Document) -> Result<Self, XmlError> {
        Ok(Self {
            inner: Rc::new(RefCell::new(ElementInner::new(
                name.to_string(),
                Some(owner_document.downgrade()),
            ))),
        })
    }

    /// Create an `Element` with child members.
    pub(crate) fn new_unchecked(name: String, owner_document: Option<WeakDocument>) -> Self {
        Self {
            inner: Rc::new(RefCell::new(ElementInner::new(name, owner_document))),
        }
    }
}

impl NodeMethod for Element {
    fn as_node(&self) -> Node {
        Node::Element(self.clone())
    }

    fn name(&self) -> String {
        self.inner.borrow().name.clone()
    }

    fn node_type(&self) -> NodeType {
        NodeType::Element
    }

    fn owner_document(&self) -> Option<Document> {
        self.inner.borrow().owner_document.clone()?.upgrade()
    }
}

impl ChildNodeInternalMethod for Element {
    fn set_parent(&mut self, parent: Option<WeakParentNode>) {
        self.inner.borrow_mut().parent = parent;
    }

    fn is_same_child_node(&self, node: &ChildNode) -> bool {
        node.as_element().map(|n| self == n).unwrap_or(false)
    }
}

impl ChildNodeMethod for Element {
    fn as_child_node(&self) -> ChildNode {
        ChildNode::Element(self.clone())
    }

    fn parent(&self) -> Option<ParentNode> {
        self.inner.borrow().parent.clone()?.upgrade()
    }
}

impl ParentNodeInternalMethod for Element {
    type WeakNode = WeakElement;

    fn downgrade(&self) -> Self::WeakNode {
        WeakElement {
            inner: Rc::downgrade(&self.inner),
        }
    }

    fn try_as_child_node(&self) -> Option<ChildNode> {
        Some(self.as_child_node())
    }

    fn is_child_allowed(&self, node: &ChildNode) -> bool {
        matches!(
            node,
            ChildNode::Element(_)
                | ChildNode::Comment(_)
                | ChildNode::Text(_)
                | ChildNode::CdataSection(_)
        )
    }
}

impl ParentNodeMethod for Element {
    fn as_parent_node(&self) -> ParentNode {
        ParentNode::Element(self.clone())
    }

    fn children(&self) -> NodeList<ChildNode> {
        self.inner.borrow().children.clone()
    }
}

impl ElementMethod for Element {
    fn attributes(&self) -> NodeMap<Attribute> {
        self.inner.borrow().attributes.clone()
    }

    fn has_attributes(&self) -> bool {
        !self.inner.borrow().attributes.is_empty()
    }

    fn contain_attribute(&self, name: &str) -> bool {
        self.inner.borrow().attributes.contains(name)
    }

    fn get_attribute(&self, name: &str) -> Option<Attribute> {
        self.inner.borrow().attributes.get(name)
    }

    fn set_attribute(&mut self, attr: Attribute) -> Option<Attribute> {
        self.inner.borrow_mut().attributes.set(attr)
    }

    fn remove_attribute(&mut self, name: &str) -> Option<Attribute> {
        self.inner.borrow_mut().attributes.remove(name)
    }

    fn get_elements(&self, name: &str) -> NodeList<Element> {
        let mut vec = Vec::new();
        let inner = self.inner.borrow();
        let list = inner.children.list.borrow();
        for node in list.iter() {
            if let Ok(element) = node.as_element() {
                if element.name() == name {
                    vec.push(element.clone());
                }
            }
        }
        NodeList::new(vec)
    }

    fn get_all_elements(&self) -> NodeList<Element> {
        let mut vec = Vec::new();
        let inner = self.inner.borrow();
        let list = inner.children.list.borrow();
        for node in list.iter() {
            if let Ok(element) = node.as_element() {
                vec.push(element.clone());
            }
        }
        NodeList::new(vec)
    }
}

impl PartialEq for Element {
    fn eq(&self, other: &Self) -> bool {
        self.inner.as_ptr() == other.inner.as_ptr()
    }
}

#[derive(Debug, Clone)]
pub struct WeakElement {
    inner: Weak<RefCell<ElementInner>>,
}

impl WeakParentNodeMethod for WeakElement {
    type Node = Element;

    fn upgrade(&self) -> Option<Self::Node> {
        self.inner.upgrade().map(|inner| Element { inner })
    }

    fn as_weak_parent_node(&self) -> WeakParentNode {
        WeakParentNode::Element(self.clone())
    }
}

impl PartialEq for WeakElement {
    fn eq(&self, other: &Self) -> bool {
        self.inner.as_ptr() == other.inner.as_ptr()
    }
}

#[derive(Debug)]
pub(crate) struct ElementInner {
    pub(crate) name: String,
    pub(crate) attributes: NodeMap<Attribute>,
    pub(crate) children: NodeList<ChildNode>,
    pub(crate) parent: Option<WeakParentNode>,
    pub(crate) owner_document: Option<WeakDocument>,
}

impl ElementInner {
    pub(crate) fn new(name: String, owner_document: Option<WeakDocument>) -> Self {
        Self {
            name,
            attributes: Default::default(),
            children: NodeList::<ChildNode>::default(),
            parent: None,
            owner_document,
        }
    }
}

#[cfg(test)]
mod ut_element {
    use crate::structure::*;

    /*
     * @title  UT test for element eq
     * @design Condition Coverage
     * @precon NA
     * @brief  1. Call `new()` method to create a document.
     *         2. Call create_element get element。
     *         3. Compare element
     * @expect 1. true。
     * @auto   yes
     */
    #[test]
    fn ut_element_eq() {
        let document = Document::new();
        let element = document.create_element("Element").unwrap();
        let weak_element = element.downgrade();
        assert_eq!(weak_element, weak_element);
    }
    /// UT test case for `Element::new()`.
    ///
    /// # Brief
    /// 1. Call `new()` method to create an `Element`.
    /// 2. Check if parts of the `Element` are default values.
    #[test]
    fn ut_element_new() {
        let document = Document::new();
        let element = Element::new("Element", &document).unwrap();
        let element_inner = element.inner.borrow();
        assert_eq!(element_inner.name, "Element");
        assert_eq!(element_inner.attributes.len(), 0);
        assert_eq!(element_inner.children.len(), 0);
        assert_eq!(element_inner.parent, None);
        assert_eq!(element_inner.owner_document, Some(document.downgrade()));
    }

    /// UT test case for `Element::as_node()`.
    ///
    /// # Brief
    /// 1. Create an `Element` called `element`.
    /// 2. Call `as_node()` method to convert `element` to `Node`.
    /// 3. Check if `Node::Element(element)` is obtained.
    #[test]
    fn ut_element_as_node() {
        let document = Document::new();
        let element = document.create_element("Element").unwrap();
        let node = element.as_node();
        assert_eq!(node, Node::Element(element));
    }

    /// UT test case for `Element::name()`.
    ///
    /// # Brief
    /// 1. Create an `Element` called `element` with a given name.
    /// 2. Call `name()` method to obtain `element`'s name.
    /// 3. Check if the obtained name is the given name.
    #[test]
    fn ut_element_name() {
        let document = Document::new();
        let element = document.create_element("Element").unwrap();
        assert_eq!(element.name(), "Element");
    }

    /// UT test case for `Element::node_type()`.
    ///
    /// # Brief
    /// 1. Create an `Element` called `element`.
    /// 2. Call `node_type()` method to obtain `element`'s type.
    /// 3. Check if this obtained node type is `NodeType::Element`.
    #[test]
    fn ut_element_node_type() {
        let document = Document::new();
        let element = document.create_element("Element").unwrap();
        assert_eq!(element.node_type(), NodeType::Element);
    }

    /// UT test case for `Element::owner_document()`.
    ///
    /// # Brief
    /// 1. Create a `Document` called `document`.
    /// 2. Create an `Element` of `element`, which is called `element`.
    /// 3. Call `owner_document()` method to obtain `element`'s owner document.
    /// 4. Check if `element`'s owner document is `Some(document)`.
    #[test]
    fn ut_element_owner_document() {
        let document = Document::new();
        let element = document.create_element("Element").unwrap();
        assert_eq!(element.owner_document(), Some(document));
    }

    /// UT test case for `Element::set_parent()`.
    ///
    /// # Brief
    /// 1. Create a `Document` called `document`.
    /// 2. Create an `Element` called `element`.
    /// 3. Call `set_parent()` method to set `element`'s parent to `document`.
    /// 4. Get the parent of `element` and check if it is the same as `document`.
    #[test]
    fn ut_element_set_parent() {
        let document = Document::new();
        let mut element = document.create_element("Element").unwrap();
        element.set_parent(Some(document.as_parent_node().downgrade()));
        assert_eq!(element.parent(), Some(document.as_parent_node()));
    }

    /// UT test case for `Element::is_same_child_node()`.
    ///
    /// # Brief
    /// 1. Create two `Element`s called `element1` and `element2`.
    /// 2. Call `as_node()` method to convert these two `Element`s into
    /// `child1` and `child2` respectively.
    /// 3. Call `is_same_child_node` method to check if `element1` is the
    /// same as `child1`.
    /// 4. Call `is_same_child_node` method to check if `element1` is the
    /// same as `child2`.
    #[test]
    fn ut_element_is_same_child_node() {
        let document = Document::new();
        let element1 = document.create_element("Element").unwrap();
        let child1 = element1.as_child_node();
        let element2 = document.create_element("Element").unwrap();
        let child2 = element2.as_child_node();

        assert!(element1.is_same_child_node(&child1));
        assert!(!element1.is_same_child_node(&child2));
    }

    /// UT test case for `Element::as_child_node()`.
    ///
    /// # Brief
    /// 1. Create an `Element` called `element`.
    /// 2. Call `as_child_node()` method to convert `element` to `ChildNode`.
    /// 3. Check if `ChildNode::Element(element)` is obtained.
    #[test]
    fn ut_element_as_child_node() {
        let document = Document::new();
        let element = document.create_element("Element").unwrap();
        let child_node = element.as_child_node();
        assert_eq!(child_node, ChildNode::Element(element));
    }

    /// UT test case for `Element::parent()`.
    ///
    /// # Brief
    /// 1. Create a `Document` called `document`.
    /// 2. Create an `Element` called `element`.
    /// 3. Call `parent()` method to check if `element` has no parent.
    /// 4. Set `comment`'s parent to `document`.
    /// 5. Call `parent()` method to check if `element`'s parent is `document`.
    #[test]
    fn ut_element_parent() {
        let mut document = Document::new();
        let element = document.create_element("Element").unwrap();
        assert_eq!(element.parent(), None);

        let _ = document.append_child(element.clone());
        assert_eq!(element.parent(), Some(document.as_parent_node()));
    }

    /// UT test case for `Element::downgrade()`.
    ///
    /// # Brief
    /// 1. Create an `Element` called `element`.
    /// 2. Call `downgrade()` method to obtained the `element`'s weak reference.
    /// 3. Check if the weak reference is valid.
    #[test]
    fn ut_element_downgrade() {
        let document = Document::new();
        let element = document.create_element("Element").unwrap();
        let weak_element = element.downgrade();
        assert_eq!(weak_element.upgrade(), Some(element));
    }

    /// UT test case for `Element::try_as_child_node()`.
    ///
    /// # Brief
    /// 1. Create an `Element` called `element`.
    /// 2. Call `try_as_child_node()` method to obtained the `ChildNode` form
    /// of `element`.
    /// 3. Check if the result is `Some(ChildNode::Element(element)`.
    #[test]
    fn ut_element_try_as_child_node() {
        let document = Document::new();
        let element = document.create_element("Element").unwrap();
        assert_eq!(
            element.try_as_child_node(),
            Some(ChildNode::Element(element))
        );
    }

    /// UT test case for `Element::is_child_allowed()`.
    ///
    /// # Brief
    /// 1. Create an `Element` called `element`.
    /// 2. Create a `Comment` called `comment`.
    /// 3. Call `is_child_allowed()` method to check if `comment` is allowed.
    #[test]
    fn ut_element_is_child_allowed() {
        let document = Document::new();
        let element = document.create_element("Element").unwrap();
        let comment = document.create_comment("Comment").unwrap();
        assert!(element.is_child_allowed(&comment.as_child_node()));
    }

    /// UT test case for `Element::as_parent_node()`.
    ///
    /// # Brief
    /// 1. Create an `Element` called `element`.
    /// 2. Call `as_parent_node()` method to convert `element` to a `ParentNode`.
    /// 3. Check if `ParentNode::Element(element)` is obtained.
    #[test]
    fn ut_element_as_parent_node() {
        let document = Document::new();
        let element = document.create_element("Element").unwrap();
        let node = element.as_parent_node();
        assert_eq!(node, ParentNode::Element(element));
    }

    /// UT test case for `Element::children()`.
    ///
    /// # Brief
    /// 1. Create an `Element` called `element`.
    /// 2. Add any number of child nodes to the `element`.
    /// 3. Call `children()` method to obtained the `element`'s children list.
    /// 4. Check if the length of the children list is correct.
    #[test]
    fn ut_element_children() {
        let document = Document::new();
        let mut element = document.create_element("Element").unwrap();
        let children = element.children();
        assert_eq!(element.children().len(), 0);

        let child = document.create_comment("Comment").unwrap();
        let child_clone = child.clone();
        let _ = element.append_child(child);
        assert_eq!(children.len(), 1);
        assert_eq!(children.item(0).unwrap(), child_clone.as_child_node());
    }

    /// UT test case for `Element::attributes()`.
    ///
    /// # Brief
    /// 1. Create an `Element` called `element`.
    /// 2. Add any number of `Attribute`s to the `element`.
    /// 3. Call `attributes()` method to obtained the `element`'s attribute list.
    /// 4. Check if the length of the attribute list is correct.
    #[test]
    fn ut_element_attributes() {
        let document = Document::new();
        let mut element = document.create_element("Element").unwrap();
        let attributes = element.attributes();
        assert_eq!(attributes.len(), 0);

        let attribute = document.create_attribute("Attribute", "Value").unwrap();
        let _ = element.set_attribute(attribute);
        assert_eq!(attributes.len(), 1);
    }

    /// UT test case for `Element::has_attributes()`.
    ///
    /// # Brief
    /// 1. Create an `Element` called `element`.
    /// 2. Add any number of `Attribute`s to the `element`.
    /// 3. Call `has_attributes()` method to check if the `element`'s attribute
    /// list is empty.
    #[test]
    fn ut_element_has_attributes() {
        let document = Document::new();
        let mut element = document.create_element("Element").unwrap();
        assert!(!element.has_attributes());

        let attribute = document.create_attribute("Attribute", "Value").unwrap();
        let _ = element.set_attribute(attribute);
        assert!(element.has_attributes());
    }

    /// UT test case for `Element::contain_attribute()`.
    ///
    /// # Brief
    /// 1. Create an `Element` called `element`.
    /// 2. Add any number of `Attribute`s to the `element`.
    /// 3. Call `contain_attribute()` method to check if an `Attribute` with the
    /// given name is in the attribute list of the `element`.
    #[test]
    fn ut_element_contain_attribute() {
        let document = Document::new();
        let mut element = document.create_element("Element").unwrap();
        assert!(!element.contain_attribute("Attribute"));

        let attribute = document.create_attribute("Attribute", "Value").unwrap();
        let _ = element.set_attribute(attribute);
        assert!(element.contain_attribute("Attribute"));
    }

    /// UT test case for `Element::get_attribute()`.
    ///
    /// # Brief
    /// 1. Create an `Element` called `element`.
    /// 2. Add any number of `Attribute`s to the `element`.
    /// 3. Call `get_attribute()` method to check if an `Attribute` with the
    /// given name is in the attribute list of the `element`.
    #[test]
    fn ut_element_get_attribute() {
        let document = Document::new();
        let mut element = document.create_element("Element").unwrap();
        assert_eq!(element.get_attribute("Attribute"), None);

        let attribute = document.create_attribute("Attribute", "Value").unwrap();
        let _ = element.set_attribute(attribute.clone());
        assert_eq!(element.get_attribute("Attribute"), Some(attribute));
    }

    /// UT test case for `Element::set_attribute()`.
    ///
    /// # Brief
    /// 1. Create an `Element` called `element`.
    /// 2. Call `set_attribute()` method to add any number of `Attribute`s to
    /// the `element`.
    /// 3. Check if the attribute list and the returned value is correct.
    #[test]
    fn ut_element_set_attribute() {
        let document = Document::new();
        let mut element = document.create_element("Element").unwrap();
        let attribute1 = document.create_attribute("Attribute", "OldValue").unwrap();
        let attribute2 = document.create_attribute("Attribute", "NewValue").unwrap();
        assert_eq!(element.set_attribute(attribute1.clone()), None);
        assert_eq!(element.get_attribute("Attribute"), Some(attribute1.clone()));
        assert_eq!(element.set_attribute(attribute2.clone()), Some(attribute1));
        assert_eq!(element.get_attribute("Attribute"), Some(attribute2));
    }

    /// UT test case for `Element::remove_attribute()`.
    ///
    /// # Brief
    /// 1. Create an `Element` called `element`.
    /// 2. Add any number of `Attribute`s to the `element`.
    /// 3. Call `remove_attribute()` method to check if an `Attribute` with the
    /// given name is removed.
    #[test]
    fn ut_element_remove_attribute() {
        let document = Document::new();
        let mut element = document.create_element("Element").unwrap();
        let attribute = document.create_attribute("Attribute", "Value").unwrap();
        let _ = element.set_attribute(attribute.clone());
        assert_eq!(element.remove_attribute("Attribute"), Some(attribute));
    }

    /// UT test case for `Element::get_element()`.
    ///
    /// # Brief
    /// 1. Create an `Element` called `element`.
    /// 2. Add any number of `Element`s to the `element`.
    /// 3. Call `get_elements()` method to check if `Element`s with the
    /// given name is in the list.
    #[test]
    fn ut_element_get_element() {
        let document = Document::new();
        let mut element1 = document.create_element("Element").unwrap();
        let element2 = document.create_element("Element").unwrap();
        let list = element1.get_elements("Element");
        assert!(list.is_empty());

        assert!(element1.append_child(element2.clone()).is_ok());
        let list = element1.get_elements("Element");
        assert_eq!(list.item(0), Some(element2));
    }

    /// UT test case for `Element::get_element()`.
    ///
    /// # Brief
    /// 1. Create an `Element` called `element`.
    /// 2. Add any number of child nodes to the `element`.
    /// 3. Call `get_all_element()` method to check if the returned list is correct.
    #[test]
    fn ut_element_get_all_element() {
        let document = Document::new();
        let mut element1 = document.create_element("Element").unwrap();
        let element2 = document.create_element("Element").unwrap();
        let element3 = document.create_element("Element").unwrap();
        let comment = document.create_comment("Comment").unwrap();

        assert!(element1.append_child(element2.clone()).is_ok());
        assert!(element1.append_child(element3.clone()).is_ok());
        assert!(element1.append_child(comment).is_ok());
        let list = element1.get_all_elements();
        assert_eq!(list.len(), 2);
        assert_eq!(list.item(0), Some(element2));
        assert_eq!(list.item(1), Some(element3));
    }
}
